package com.watson.onebox.algorithm.descarte;
import com.watson.onebox.algorithm.descarte.User;

import java.util.*;

public class Descartes {


    /**
     * 递归实现dimValue中的笛卡尔积，结果放在result中
     *
     * @param dimValue 原始数据
     * @param result   结果数据
     * @param layer    dimValue的层数
     * @param curList  每次笛卡尔积的结果
     */
    private static void recursive(List<List<String>> dimValue, List<List<String>> result, int layer, List<String> curList) {
        if (layer < dimValue.size() - 1) {
            if (dimValue.get(layer).size() == 0) {
                recursive(dimValue, result, layer + 1, curList);
            } else {
                for (int i = 0; i < dimValue.get(layer).size(); i++) {
                    List<String> list = new ArrayList<String>(curList);
                    list.add(dimValue.get(layer).get(i));
                    recursive(dimValue, result, layer + 1, list);
                }
            }
        } else if (layer == dimValue.size() - 1) {
            if (dimValue.get(layer).size() == 0) {
                result.add(curList);
            } else {
                for (int i = 0; i < dimValue.get(layer).size(); i++) {
                    List<String> list = new ArrayList<String>(curList);
                    list.add(dimValue.get(layer).get(i));
                    result.add(list);
                }
            }
        }
    }
/*

    */
/**
     * 递归实现dimValue中的笛卡尔积，结果放在result中
     *
     * @param dimValue 原始数据
     * @param result   结果数据
     * @param layer    dimValue的层数
     * @param curList  每次笛卡尔积的结果
     *//*

    private static void recursive1(Class<? extends Cloneable> claz,
                                   Map<String, List<Object>> dimValue,
                                   List<Object> result,
                                   List<String> key,
                                   int layer,
                                   Object curList) {
        if (layer < dimValue.size() - 1) {
            if (dimValue.get(layer) == null) {
                recursive1(claz, dimValue, result, key, layer + 1, curList);
            } else {
                List<Object> params = dimValue.get(key.get(layer));

                for (Object param : params) {
                    Object newCur = curList.clone();

                }


                for (int i = 0; i < dimValue.get(layer).size(); i++) {
                    List<String> list = new ArrayList<String>(curList);
                    list.add(dimValue.get(layer).get(i));
                    recursive1(claz ,dimValue, result, key, layer + 1, list);
                }
            }
        } else if (layer == dimValue.size() - 1) {
            if (dimValue.get(layer).size() == 0) {
                result.add(curList);
            } else {
                for (int i = 0; i < dimValue.get(layer).size(); i++) {
                    List<String> list = new ArrayList<String>(curList);
                    list.add(dimValue.get(layer).get(i));
                    result.add(list);
                }
            }
        }
    }
*/

    /**
     * 循环实现dimValue中的笛卡尔积，结果放在result中
     *
     * @param dimValue 原始数据
     * @param result   结果数据
     */
    private static void circulate(List<List<String>> dimValue, List<List<String>> result) {
        int total = 1;
        //计算乘积总数
        for (List<String> list : dimValue) {
            total *= list.size();
        }
        String[] myResult = new String[total];

        int now = 1;
        for (List<String> list : dimValue) {
            now *= list.size();

            int index = 0;
            int currentSize = list.size();

            int itemLoopNum = total / now;
            int loopPerItem = now / currentSize;
            int myIndex = 0;

            for (String string : list) {
                for (int i = 0; i < loopPerItem; i++) {
                    if (myIndex == list.size()) {
                        myIndex = 0;
                    }

                    for (int j = 0; j < itemLoopNum; j++) {
                        myResult[index] = (myResult[index] == null ? "" : myResult[index] + ",") + list.get(myIndex);
                        index++;
                    }
                    myIndex++;
                }

            }
        }

        String[] stringResult = myResult;
        for (String string : stringResult) {
            String[] stringArray = string.split(",");
            result.add(Arrays.asList(stringArray));
        }
    }


    /**
     * 循环实现dimValue中的笛卡尔积，结果放在result中
     *
     * @param dimValue 原始数据
     * @param result   结果数据
     */
    private static void circulate1(Class claz,
                                   Map<String, List<Object>> dimValue,
                                   List<Object> result) {
        int total = 1;
        for (String s : dimValue.keySet()) {
            total *= dimValue.get(s).size();
        }

        //创建所有的bean
        List<DynamicBean> beanMapList = new ArrayList<>();
        for (int i = 0; i < total; i++) {
            try {
                Class<?> aClass = Class.forName(claz.getName());
                Object o = aClass.newInstance();
                beanMapList.add(new DynamicBean(o));
            } catch (ClassNotFoundException e) {
                e.printStackTrace();
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            } catch (InstantiationException e) {
                e.printStackTrace();
            }
        }

        int itemLoopNum;
        int loopPerItem;
        int now = 1;
        Iterator<Map.Entry<String, List<Object>>> iterator = dimValue.entrySet().iterator();
        while (iterator.hasNext()) {
            Map.Entry<String, List<Object>> next = iterator.next();
            List<Object> list = next.getValue();

            now *= list.size();

            int index = 0;
            int currentSize = list.size();

            itemLoopNum = total / now;
            loopPerItem = total / (itemLoopNum * currentSize);
            int myIndex = 0;

            for (Object object : list) {
                for (int i = 0; i < loopPerItem; i++) {
                    if (myIndex == list.size()) {
                        myIndex = 0;
                    }

                    for (int j = 0; j < itemLoopNum; j++) {
                        DynamicBean dynamicBean = beanMapList.get(index);
                        dynamicBean.setValue(next.getKey(), list.get(myIndex));
                        index++;
                    }
                    myIndex++;
                }

            }
        }
        for (DynamicBean dynamicBean : beanMapList) {
            result.add(dynamicBean.getObject());
        }
    }

    /**
     * 递归实现dimValue中的笛卡尔积，结果放在result中
     *
     * @param dimValue 原始数据
     * @param result   结果数据
     * @param layer    dimValue的层数
     * @param curList  每次笛卡尔积的结果
     */
    private static void recursiveBean(List<List<User>> dimValue, List<List<User>> result, int layer, List<User> curList) {
        if (layer < dimValue.size() - 1) {
            if (dimValue.get(layer).size() == 0) {
                recursiveBean(dimValue, result, layer + 1, curList);
            } else {
                for (int i = 0; i < dimValue.get(layer).size(); i++) {
                    List<User> list = new ArrayList<User>(curList);
                    list.add(dimValue.get(layer).get(i));
                    recursiveBean(dimValue, result, layer + 1, list);
                }
            }
        } else if (layer == dimValue.size() - 1) {
            if (dimValue.get(layer).size() == 0) {
                result.add(curList);
            } else {
                for (int i = 0; i < dimValue.get(layer).size(); i++) {
                    List<User> list = new ArrayList<User>(curList);
                    list.add(dimValue.get(layer).get(i));
                    result.add(list);
                }
            }
        }
    }

    /**
     * 程序入口
     *
     * @param args
     */
    public static void main(String[] args) {
        Map<String, List<Object>> pageTypeName = new HashMap<>();


        Map<String, List<Object>> paramMap = new HashMap<>();
        List<Object> erp = new ArrayList<>();
        erp.add("123");
        erp.add("213");
        erp.add("243");
        paramMap.put("erp", erp);

        pageTypeName.put("stat", erp);
        System.out.println(pageTypeName);
        List<Object> tab = new ArrayList<>();
        tab.add("123");
        tab.add("213");
        tab.add("313");
        paramMap.put("tab", tab);


        List<Object> system = new ArrayList<>();
        List<String> abc1 = new ArrayList<>();
        abc1.add("fa");
        abc1.add("e1f");
        system.add(abc1);
        List<String> abc2 = new ArrayList<>();
        abc2.add("1313");
        abc2.add("fewo");
        system.add(abc2);
        paramMap.put("systems", system);

        System.out.println(paramMap.values());
        List<Object> result = new ArrayList<>();
        circulate1(TableVo.class, paramMap, result);



        List<String> list1 = new ArrayList<String>();
        list1.add("1");
        list1.add("2");

        List<String> list2 = new ArrayList<String>();
        list2.add("a");
        list2.add("b");

        List<String> list3 = new ArrayList<String>();
        list3.add("3");
        list3.add("4");
        list3.add("5");

        List<String> list4 = new ArrayList<String>();
        list4.add("c");
        list4.add("d");
        list4.add("e");

        List<List<String>> dimValue = new ArrayList<List<String>>();
        dimValue.add(list1);
        dimValue.add(list2);
        dimValue.add(list3);
        dimValue.add(list4);

        List<List<String>> recursiveResult = new ArrayList<List<String>>();
        // 递归实现笛卡尔积
        recursive(dimValue, recursiveResult, 0, new ArrayList<String>());

        System.out.println("递归实现笛卡尔乘积: 共 " + recursiveResult.size() + " 个结果");
        for (List<String> list : recursiveResult) {
            for (String string : list) {
                System.out.print(string + " ");
            }
            System.out.println();
        }

        List<List<String>> circulateResult = new ArrayList<List<String>>();
        circulate(dimValue, circulateResult);
        System.out.println("循环实现笛卡尔乘积: 共 " + circulateResult.size() + " 个结果");
        for (List<String> list : circulateResult) {
            for (String string : list) {
                System.out.print(string + " ");
            }
            System.out.println();
        }


        List<User> users1 = new ArrayList<User>();
        users1.add(new User(1, "张三丰"));
        users1.add(new User(2, "逍遥子"));

        List<User> users2 = new ArrayList<User>();
        users2.add(new User(3, "扫地僧"));
        users2.add(new User(4, "王语嫣"));

        List<User> users3 = new ArrayList<User>();
        users3.add(new User(5, "花千落"));
        users3.add(new User(6, "林水寒"));

        List<User> users4 = new ArrayList<User>();
        users4.add(new User(7, "易天行"));
        users4.add(new User(8, "张无忌"));

        List<List<User>> dimValueList = new ArrayList<List<User>>();
        dimValueList.add(users1);
        dimValueList.add(users2);
        dimValueList.add(users3);
        dimValueList.add(users4);

        List<List<User>> recursiveResultList = new ArrayList<List<User>>();
        // 递归实现笛卡尔积
        recursiveBean(dimValueList, recursiveResultList, 0, new ArrayList<User>());

        System.out.println("Bean集合递归实现笛卡尔乘积: 共 " + recursiveResult.size() + " 个结果");
        for (List<User> list : recursiveResultList) {
            for (User user : list) {
                System.out.print(user);
            }
            System.out.println();
        }
    }

}
